#region File Description
// -----------------------------------------------------------------------------
// Primitives3DGame.cs
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
// -----------------------------------------------------------------------------
#endregion

#region Using Statements
#endregion

namespace UnityEngine
{
    using System.Collections.Generic;
    using Microsoft.Xna.Framework;
    using UnityEngine.Components;
    using UnityEngine.Core;
    using UnityEngine.Graphics;
    using Microsoft.Xna.Framework.Input;
    using UnityEngine.IO;
    using UnityEngine.Graphics.Shader;
    using Microsoft.Xna.Framework.Graphics;
    using System;
    using System.Diagnostics;
    using UnityEngine.Graphics.Texture;
    using UnityEngine.Graphics.Text;
    using UnityEngine.Audio;

    /// <summary>
    /// This sample shows how to draw 3D geometric primitives
    /// such as cubes, spheres, and cylinders.
    /// </summary>
    public class UnityEngineGame : Microsoft.Xna.Framework.Game
    {
        protected GraphicsDeviceManager graphics;

        public InputManager InputManager
        {
            get;
            set;
        }

        private GameScene gameScene = null;

        private GameSettings _Settings;
        public GameSettings GameSettings
        {
            get
            {
                return _Settings;
            }
            set
            {
                _Settings = value;
            }
        }

        public bool IsAWindowGame
        {
            get;
            set;
        }

        public UnityEngineGame()
        {
            this.IsFixedTimeStep = true;
            this.TargetElapsedTime = TimeSpan.FromSeconds(1.0f / 60.0f);
            this.Content.RootDirectory = "..\\..\\UnityEngineContent";
            this.graphics = new GraphicsDeviceManager(this);
            Window.AllowUserResizing = true;
            EffectManager.Instance.ResetDevice();
            InputManager = new InputManager(this);

            this.GameSettings = new GameSettings();
            this.IsAWindowGame = true;
        }

        public GameScene GameScene
        {
            set
            {
                bool differ = (gameScene != value) && (value != null);
                gameScene = value;
                if (differ)
                {
                    gameScene.Game = this;
                    if (gameScene.IsNeedReset)
                        gameScene.Reset();
                }
            }
            get
            {
                return gameScene;
            }
        }

        private Dictionary<string, ModelRenderer> ModelRenderers
        {
            get;
            set;
        }

        public void Startup(GameTime gameTime)
        {
            if (this.IsAWindowGame)
            {
                Time.Initialize();
            }
            if (this.GameScene != null)
                this.GameScene.Startup(gameTime);
        }

        protected override void Update(GameTime gameTime)
        {
            this.InputManager.Update(gameTime);

            if (this.GameScene != null)
                GameScene.Update(gameTime);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            if (this.IsAWindowGame)
            {
                Time.Tick();
                this.GraphicsDevice.Clear(Color.Transparent);
            }

            if (this.GameScene != null)
                GameScene.Draw(gameTime);

            base.Draw(gameTime);
        }

        protected override void Initialize()
        {
            if (IsAWindowGame)
            {
                this.GameScene = IOManager.Instance.LoadGameScene(GameSettings.StartScenePath);
                this.GameScene.Mode = SceneMode.NormalMode;

                this.GameSettings = this.GameScene.GetComponentInChildren<GameSettings>();
                this.graphics.PreferredBackBufferWidth = this.GameSettings.ScreenWidth;
                this.graphics.PreferredBackBufferHeight = this.GameSettings.ScreenHeight;
                this.graphics.IsFullScreen = GameSettings.IsFullScreen;
                this.graphics.ApplyChanges();

                this.IsMouseVisible = GameSettings.IsMouseVisible;
                Window.AllowUserResizing = false;
                Window.Title = GameSettings.Title;
                this.InputManager.ClipRectangle = new Rectangle(0, 0, this.GraphicsDevice.Viewport.Width, this.GraphicsDevice.Viewport.Height);
            }
            base.Initialize();
        }

        protected override void OnExiting(object sender, EventArgs args)
        {
            this.Dispose(true);
            base.OnExiting(sender, args);
        }

        public new void Dispose()
        {
            this.Dispose(true);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                SceneManager.SingletonDispose();

                TextureManager.SingletonDispose();

                EffectManager.SingletonDispose();

                FontStorage.SingletonDispose();

                AudioManager.SingletonDispose();
            }
        }

        protected override void LoadContent()
        {
            EffectManager.Instance.Shader.LoadContent(this.Content);

            if (IsAWindowGame)
            {
                this.Startup(new GameTime());
            }
            base.LoadContent();
        }
    }

    #region Entry Point

    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    public static class Program
    {
        public static void Main()
        {
            using (UnityEngineGame game = new UnityEngineGame())
            {
                game.Run();
            }
        }
    }

    #endregion
}
